<?php
/**
 *
 * UtilFunction.php
 *
 * 工具集函数类
 *
 *　
 */

namespace Deyi\Functions;

use Apps\Common\Constant\CacheKeyConstant;
use Apps\Common\Constant\CacheTimeoutConstant;
use Phalcon\Di;
use Vendor\HtmlPurifier\HP;

/**
 * Class UtilFunction
 */
class UtilFunction
{
    /**
     * 获取客户端IP
     *
     * @return string
     */
    public static function getClientIp()
    {
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $tmp = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            return trim($tmp[0]);
        } elseif (isset($_SERVER['HTTP_X_REAL_IP'])) {
            return $_SERVER['HTTP_X_REAL_IP'];
        } else {
            return $_SERVER['REMOTE_ADDR'];
        }
    }

    /**
     *  获取用户访问的端口号
     *
     * @return mixed
     */
    public static function getClientPort()
    {
        return $_SERVER['REMOTE_PORT'];
    }

    /**
     * 检查手机号码合法性
     * @param $mobile
     * @return bool
     */
    public static function checkMobileFormat($mobile)
    {
        if (empty($mobile)) {
            return false;
        }

        if (mb_strlen($mobile) !== 11) {
            return false;
        }

        if (!preg_match('/^1[0-9]{10}$/', $mobile)) {
            return false;
        }

        return true;
    }

    /**
     * 检查身份证号
     * @param $idCard
     * @return bool
     */
    public static function checkIDCardFormat($idCard)
    {
        $id = strtoupper($idCard);
        $regx = "/(^\d{15}$)|(^\d{17}([0-9]|X)$)/";
        $arr_split = array();
        if (!preg_match($regx, $id)) {
            return false;
        }
        //检查15位
        if (15 == strlen($id)) {
            $regx = "/^(\d{6})+(\d{2})+(\d{2})+(\d{2})+(\d{3})$/";

            @preg_match($regx, $id, $arr_split);
            //检查生日日期是否正确
            $dtm_birth = "19" . $arr_split[2] . '/' . $arr_split[3] . '/' . $arr_split[4];
            if (!strtotime($dtm_birth)) {
                return false;
            } else {
                return true;
            }
        } else {
            //检查18位
            $regx = "/^(\d{6})+(\d{4})+(\d{2})+(\d{2})+(\d{3})([0-9]|X)$/";
            @preg_match($regx, $id, $arr_split);
            $dtm_birth = $arr_split[2] . '/' . $arr_split[3] . '/' . $arr_split[4];
            //检查生日日期是否正确
            if (!strtotime($dtm_birth)) {
                return false;
            } else {
                //检验18位身份证的校验码是否正确。
                //校验位按照ISO 7064:1983.MOD 11-2的规定生成，X可以认为是数字10。
                $arr_int = array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
                $arr_ch = array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
                $sign = 0;
                for ($i = 0; $i < 17; $i++) {
                    $b = (int)$id{$i};
                    $w = $arr_int[$i];
                    $sign += $b * $w;
                }
                $n = $sign % 11;
                $val_num = $arr_ch[$n];
                if ($val_num != substr($id, 17, 1)) {
                    return false;
                } else {
                    return true;
                }
            }
        }
    }

    public static function filterXSS($str)
    {
        return HP::getInstance()->filterXss($str);
    }

    public static function encryptBase64($str, $key = null)
    {
        return Di::getDefault()->get('crypt')->encryptBase64(strval($str), $key);
    }

    /**
     * 导出 excel
     *
     * @param $filename
     * @param $data
     *
     * @return bool
     */
    public static function exportCsv($filename, $data)
    {

        header("Content-type:text/csv");
        header("Content-Disposition:attachment; filename=" . $filename);
        header('Cache-Control:must-revalidate, post-check=0, pre-check=0');
        header('Expires:0');
        header('Pragma:public');

        echo $data;
        exit;
    }

    public static function logInFile($type, $word)
    {
        return true;

        $path = dirname(dirname(dirname(__DIR__))) . '/public';

        if (!file_exists($path)) {
            //self::createFolder(dirname($path));
            mkdir($path, 0777);
        }

        //var_dump($path);exit;

        $filename = 'l.txt';
        $fp = fopen($path . "/{$filename}", "a");
        flock($fp, LOCK_EX);
        fwrite($fp,
            "类型：$type\n\r时刻：" . date('Y-m-d H:i:s') . "\n\r内容：\n\r" . $word . "\n\r----------------------\n\r\n\r");
        flock($fp, LOCK_UN);
        fclose($fp);

    }

    /**
     * 根据服务器本地网卡MAC地址计算服务器唯一标识
     *
     * @author liang<lang@vip.deyi.com>
     * @param string $custom
     * @return bool|string
     */
    public static function getServerUniqueId($custom = '')
    {

        if (!empty($custom)) {
            return $custom;
        }

        //根据网卡标识来计算
        $ifconfig = shell_exec('/sbin/ifconfig');
        preg_match(
            '/inet.*?$/mi',
            $ifconfig,
            $match
        );

        if ($match && isset($match[0])) {
            return md5($match[0]);
        } else {
            return false;
        }
    }

    /**
     *  获取文件后缀名
     *
     * @author liang<lang@vip.deyi.com>
     * @param $filename
     * @return mixed
     */
    public static function getExtensionName($filename)
    {
        if (empty($filename)) {
            return '';
        }

        $ret = explode('.', $filename);

        if (count($ret) == 1) {
            return '';
        }

        return end($ret);
    }

    /**
     *  生成随机字符串
     *
     * @author liang<lang@vip.deyi.com>
     * @param int $length
     * @return string
     */
    public static function getRandomString($length = 32)
    {
        $str = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ#!@%*+_-.?';
        $ret = '';
        $strLen = strlen($str) - 1;
        for ($i = 0; $i < $length; $i++) {
            $num = mt_rand(0, $strLen);
            $ret .= $str[$num];
        }

        return $ret;
    }

    public static function getRandomInteger($min, $max)
    {
        if (!$max) {
            return 0;
        }

        if (version_compare(PHP_VERSION, '7.0.0', '>=')) {
            return random_int($min, $max);
        } else {
            list($usec, $sec) = explode(' ', microtime());
            mt_srand((float)$sec + ((float)$usec * 100000));
            return mt_rand($min, $max);
        }
    }

    /**
     * 获取指定字符串被分隔后的第一个数据值
     *
     * @author liang<lang@vip.deyi.com>
     * @param $str
     * @param $delimiter
     * @return mixed
     */
    public static function getFirstByDelimiter($str, $delimiter)
    {
        $tmp = explode($delimiter, $str);

        return $tmp[0];
    }

    /**
     * 根据UserAgent判断是否是移动设备
     *
     * @author liang<lang@vip.deyi.com>
     * @param $userAgent
     * @return bool
     */
    public static function isMobileDevice($userAgent)
    {
        if (preg_match('/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i',
                $userAgent) || preg_match(
                '/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i',
                substr($userAgent, 0, 4))
        ) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * XML对象转换为array
     *
     * @author liang<lang@vip.deyi.com>
     * @param $object
     * @return mixed
     */
    public static function xmlObject2Array($object)
    {
        return @json_decode(@json_encode($object), 1);
    }

    /**
     * 获取一个随机浮点数
     *
     * @author liang<lang@vip.deyi.com>
     * @param $min
     * @param $max
     * @param $decimal
     * @return mixed
     */
    public static function getRandomFloat($min, $max, $decimal = 8)
    {
        return sprintf('%.' . $decimal . 'f', ($min + lcg_value() * (abs($max - $min))));
    }

    /**
     * 闭合标签检查函数
     * @author lang@vip.deyi.com
     * @param $htmlText
     * @return bool
     */
    public static function closedHtmlTagChecker($htmlText)
    {
        $tags = [
            '<div>' => '</div>',
            '<p>' => '</p>',
            '<font>' => '</font>',
            '<i>' => '</i>',
            '<strong>' => '</strong>',
            '<b>' => '</b>',
            '<h1>' => '</h1>',
            '<h2>' => '</h2>',
            '<h3>' => '</h3>',
            '<h4>' => '</h4>',
            '<h5>' => '</h5>',
            '<h6>' => '</h6>',
        ];
        $htmlText = strtolower($htmlText);

        foreach ($tags as $k => $v) {
            if (mb_substr_count($htmlText, $k) !== mb_substr_count($htmlText, $v)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 添加图片地址
     * @version APP6.3.0
     * @author lang@vip.deyi.com
     * @param $prefixHost
     * @param $imgUrl
     * @return string
     */
    public static function addImagePrefixHost($prefixHost, $imgUrl)
    {
        if (stripos($imgUrl, 'http') === 0 || stripos($imgUrl, '//') === 0) {
            return $imgUrl;
        }

        return $prefixHost . $imgUrl;
    }

    /**
     * 获取图片类型
     * @version APP6.3.0
     * @author lang@vip.deyi.com
     * @param $file
     * @return string
     */
    public static function getImageTypeInfo($file)
    {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $fileType = finfo_file($finfo, $file);
        $fileExt = '';
        switch ($fileType) {
            case 'image/jpg':
            case 'image/jpeg':
            case 'image/pjpeg':
                $fileExt = 'jpg';
                break;
            case 'image/png':
            case 'image/x-png':
                $fileExt = 'png';
                break;
            case 'image/gif':
                $fileExt = 'gif';
                break;
            case 'image/webp':
                $fileExt = 'webp';
                break;
        }

        return $fileExt;
    }

    /**
     * 获取文件MIME类型
     * @author lang@vip.deyi.com
     * @param $file
     * @return mixed
     */
    public static function getFileMimeType($file)
    {
        return finfo_file(finfo_open(FILEINFO_MIME_TYPE), $file);
    }

    /**
     * 根据指定字符串生成一个短字符串
     * @version APP 6.3.5
     * @author lang@vip.deyi.com
     * @param $input
     * @return string
     */
    public static function getShortSymbol($input)
    {
        $charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
        $key = '7Uw8nrBl'; //加盐
        $urlhash = md5($key . $input);
        $len = strlen($urlhash);
        $short_url_list = [];
        //将加密后的串分成4段，每段4字节，对每段进行计算，一共可以生成四组短连接
        for ($i = 0; $i < 4; $i++) {
            $urlhash_piece = substr($urlhash, $i * $len / 4, $len / 4);

            //将分段的位与0x3fffffff做位与，0x3fffffff表示二进制数的30个1，即30位以后的加密串都归零
            //此处需要用到hexdec()将16进制字符串转为10进制数值型，否则运算会不正常
            $hex = hexdec($urlhash_piece) & 0x3fffffff;

            //域名根据需求填写
            $short_url = '';

            //生成6位短网址
            for ($j = 0; $j < 6; $j++) {

                //将得到的值与0x0000003d,3d为61，即charset的坐标最大值
                $short_url .= $charset[$hex & 0x0000003d];

                //循环完以后将hex右移5位
                $hex = $hex >> 5;
            }

            $short_url_list[] = $short_url;
        }

        // 选取第一段和第三段组合成一个字符串
        return $short_url_list[0] . $short_url_list[2];
    }

    /**
     * 将url中参数拆解成数组形态
     * @version APP 6.3.5
     * @author lang@vip.deyi.com
     * @param $query
     * @return array
     */
    public static function getUrlQueryArray($query)
    {
        $queryParts = explode('&', $query);
        $params = [];
        foreach ($queryParts as $param) {
            $item = explode('=', $param);
            $params[$item[0]] = $item[1];
        }
        return $params;
    }

    /**
     * 获取手机号归属地
     * @author lang@vip.deyi.com
     * @param $mobile
     * @return string
     */
    public static function getMobileLocation($mobile)
    {
        $cacheKey = CacheFunction::generateKey(CacheKeyConstant::MOBILE_LOCATION_INFO_CACHE_KEY, $mobile);

        $res = apcu_fetch($cacheKey);

        if ($res) {
            return $res;
        }

        $res = 'none';
        $ret = HttpFunction::getPage('http://chongzhi.jd.com/json/order/search_searchPhone.action?mobile=' . $mobile, 2);
        if ($ret && ($ret = mb_convert_encoding($ret, 'utf-8', 'gbk')) && ($ret = json_decode($ret)) && isset($ret->providerName)) {
            $res = $ret->areaName . $ret->providerName;
        }
        apcu_store($cacheKey, $res, CacheTimeoutConstant::LOCAL_HOUR_CACHE);
        return $res;
    }

    /**
     * 根据经纬度获取地理位置
     * @version APP 6.3.7
     * @author lang@vip.deyi.com
     * @param $long //经度
     * @param $lat //纬度
     * @param $coordType //坐标类型
     * @return array|bool
     */
    public static function getCoordinateLocation($long, $lat, $coordType = 'bd09ll')
    {
        $url = sprintf('https://api.map.baidu.com/geocoder/v2/?callback=renderReverse&location=%s,%s&output=json&pois=0&ak=%s&coordtype=%s',
            $lat,
            $long,
            Di::getDefault()->get('config')->baidumap->ak,
            $coordType
        );

        $ret = HttpFunction::getPage($url);

        $ret = str_replace('renderReverse&&renderReverse(', '', rtrim($ret, ')'));

        $json = json_decode($ret);

        if ($json) {
            if (!$json->status) {
                return [
                    'address' => isset($json->result->formatted_address) ? $json->result->formatted_address : '',
                    'country' => isset($json->result->addressComponent->country) ? $json->result->addressComponent->country : '',
                    'province' => isset($json->result->addressComponent->province) ? $json->result->addressComponent->province : '',
                    'city' => isset($json->result->addressComponent->city) ? $json->result->addressComponent->city : '',
                    'district' => isset($json->result->addressComponent->district) ? $json->result->addressComponent->district : '',
                    'street' => isset($json->result->addressComponent->street) ? $json->result->addressComponent->street : '',
                    'addr_desc' => isset($json->result->sematic_description) ? $json->result->sematic_description : ''
                ];
            } else {
                Di::getDefault()->get('logger')->error('Baidumap get failed:' . $json->status);
            }
        }

        return false;
    }

    public static function listDir($dir, $prefix = '')
    {
        $files = [];
        if (is_dir($dir)) {
            if ($dh = opendir($dir)) {
                while (($file = readdir($dh)) !== false) {
                    if ($file == '.' || $file == '..') {
                        continue;
                    }

                    if ($prefix && (strpos($file, $prefix) !== 0)) {
                        continue;
                    }

                    $filePath = $dir . $file;
                    $files[] = [
                        'filename' => $file,
                        'dateline' => filemtime($filePath),
                        'filesize' => filesize($filePath)
                    ];
                }
                closedir($dh);
            }
        }
        return $files;
    }

    public static function encryptUrlParam($str, $crypt = '')
    {
        return rawurlencode(Di::getDefault()->get('crypt')->encryptBase64($str . '', $crypt));
    }

    public static function decryptUrlParam($str, $crypt = '')
    {
        return Di::getDefault()->get('crypt')->decryptBase64(rawurldecode($str . ''), $crypt);
    }

    public static function urlsafe_b64encode($string) {
        $data = base64_encode($string);
        $data = str_replace(array('+','/','='),array('-','_',''),$data);
        return $data;
    }
    
    public static function  urlsafe_b64decode($string) {
        $data = str_replace(array('-','_'),array('+','/'),$string);
        $mod4 = strlen($data) % 4;
        if ($mod4) {
            $data .= substr('====', $mod4);
        }
        return base64_decode($data);
    }
}
